package cn.zyx.user.service.impl;

import cn.zyx.basic.exception.BusinessException;
import cn.zyx.basic.util.SmsUtils;
import cn.zyx.basic.util.StrUtils;
import cn.zyx.user.constant.UserConstant;
import cn.zyx.user.domain.User;
import cn.zyx.user.service.IUserService;
import cn.zyx.user.service.IVerifyCodeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 *  1. 校验
 *      1.1 校验手机号是不是为空
 *      1.2 校验手机号是否被注册过
 *  2. 判断是否存在验证码 --> 从redis中获取电话对应的验证码
 *      2.1 如果存在验证码
 *          2.1.1 判断是否过了1分钟的重发时间
 *              2.1.1.1 如果没有过1分钟的重发时间，抛出异常：请勿重复发送
 *              2.1.1.2 如果过了1分钟的重发时间，使用原来还没有过期的验证码，并且刷新验证码的过期时间
 *      2.2 如果不存在验证码，就直接生成验证码
 *   3. 保存验证码到redis，设置过期时间
 *   4. 发送短信 --> 使用工具类掉短信接口即可
 */
@Service
public class VerifyCodeServiceImpl implements IVerifyCodeService {

    @Autowired
    private IUserService userService;
    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public void sendSmsCode(Map<String,String> param) {
        // 获取参数
        String phone = param.get("phone");
        String type = param.get("type");
        // 校验
        // 校验参数是否为空
        if (!StringUtils.hasLength(phone) || !StringUtils.hasLength(type)){
            throw new BusinessException("必要参数不能为空!");
        }
        // 判断前端传过来的type，做不同的业务区分
        if ("register".equals(type)){
            // 校验手机号是否被注册过
            User user = userService.loadByPhone(phone);
            if (user != null){
                throw new BusinessException("手机号已经注册!");
            }
            String businessKey = UserConstant.USER_VERFIY_CODE+":"+phone;
            sendSmsCode(businessKey);
        }else if ("binder".equals(type)){
            String businessKey = UserConstant.USER_BINDER_CODE+":"+phone;
            sendSmsCode(businessKey);
        }
    }

    /**
     * 提取出来的发送验证码的方法
     * @param businessKey
     */
    public void sendSmsCode(String businessKey){
        // 判断是否存在验证码 --> 从redis中获取电话对应的验证码
        Object codeObj = redisTemplate.opsForValue().get(businessKey);
        String code = "";
        // 不为空，表示存在验证码
        if (codeObj != null){
            String value = (String) codeObj;    // 强转为string类型
            // 获取原来验证码的时间戳
            String timeStr = value.split(":")[1];
            // 判断是否过了一分钟的重发时间
            if (System.currentTimeMillis() - Long.valueOf(timeStr) <= 1*60*1000){
                // 如果没有过1分钟的重发时间，抛出异常：请勿重复发送
                throw new BusinessException("请勿重复发送!");
            }
            // 如果过了1分钟的重发时间，使用原来还没有过期的验证码，并且刷新验证码的过期时间
            code = value.split(":")[0];
        }else { // 不为空，表示不存在验证码
            // 直接生成验证码
            code = StrUtils.getComplexRandomString(4);
        }
        // 拼接储存验证码的格式
        String codeValue = code + ":" + System.currentTimeMillis();
        // 保存验证码到redis，设置过期时间
        redisTemplate.opsForValue().set(businessKey,codeValue,3,TimeUnit.MINUTES);
        // 发送短信 --> 使用工具类掉短信接口即可
        // SmsUtils.sendSms(phone,  "您的验证码是："+code+"; 请在3分钟内使用！");
        // 这里直接打印，发短信要钱
        System.out.println("您的验证码是："+code+"; 请在3分钟内使用！");
    }
}
